package com.rlevin.java.chmod;
import com.rlevin.java.chmod.Permissions;
import java.util.HashMap;

/**
 * @author Rob Levin
 * @see Permissions
 */

public class Ugo {
	
	private enum Ugos {
		USER("User"),
		GROUP("Group"),
		OTHER("Other");
		
		private String whom;
		
		private Ugos(String whoItBe) {
			this.whom = whoItBe;
		}
		
		public String toString() {
			return this.whom;
		}
	}
	
	/**
	 * TODO: Legal input is 111-777, and 000 doesn't work even though it's valid!
	 * @param iChmodArg
	 */
	public void chmod(String sChmod) {
		int iChmodArg = this.validateChmodArgs(sChmod);
		if(iChmodArg==(this.getPermissionsAsInt())) {
			return;	// permissions are the same so don't need to do anything ;)
		}
		this.chmodStringToUpdatedUgo(sChmod);	// Helper updates the permissions on the UGO
	}
	
	private int validateChmodArgs(String sChmod) {
		int iChmodArg = Integer.parseInt(sChmod);
		if(sChmod.length() != 3) {
			throw new IllegalArgumentException("chmod requires a three digit int between 111-777.");
		} else if (iChmodArg < 0 ||  iChmodArg > 777) {
			throw new IllegalArgumentException("chmod requires a three digit int between 111-777.");
		}
		return iChmodArg;
	}

	private void chmodStringToUpdatedUgo (String sChmod) {
		int iUserPerms  = Character.digit(sChmod.charAt(0), 10);
		int iGroupPerms = Character.digit(sChmod.charAt(1), 10);
		int iOtherPerms = Character.digit(sChmod.charAt(2), 10);
		
		// Leading zero not allowed at this point
		if(iUserPerms==0) throw new IllegalArgumentException("chmod does not currently allow leading zero.");
		
		//Note to self from javadocs: 'If the map previously contained a mapping for this key, the old value is replaced.'
		accessEntities.put(Ugos.USER.toString (), new User (Permissions.createAPermissionByInt(iUserPerms )));
		accessEntities.put(Ugos.GROUP.toString(), new Group(Permissions.createAPermissionByInt(iGroupPerms)));
		accessEntities.put(Ugos.OTHER.toString(), new Other(Permissions.createAPermissionByInt(iOtherPerms)));
	}
	
	public int getPermissionsAsInt() {
		int iUserPerms	= this.getUser().getPermissions().getPermissionsLevelAsInt();
		int iGroupPerms = this.getGroup().getPermissions().getPermissionsLevelAsInt();
		int iOtherPerms	= this.getOther().getPermissions().getPermissionsLevelAsInt();
		
		int iUGO = (iUserPerms*100) + (iGroupPerms*10) + iOtherPerms;
		
		return iUGO;
	}
	private HashMap<String, Chmodable> accessEntities;
	
	public Chmodable getUser() {
		return accessEntities.get(Ugos.USER.toString());
	}
	
	public Chmodable getGroup() {
		return accessEntities.get(Ugos.GROUP.toString());
	}
	
	public Chmodable getOther() {
		return accessEntities.get(Ugos.OTHER.toString());
	}
	
	
	public Ugo (Chmodable user, Chmodable group, Chmodable other) {
		accessEntities = new  HashMap<String, Chmodable>();
		accessEntities.put(Ugos.USER.toString(), user);
		accessEntities.put(Ugos.GROUP.toString(), group);
		accessEntities.put(Ugos.OTHER.toString(), other);
	}
	
	public String toString () {
		return Ugos.USER.toString()  + "  Permisions: " + 
					accessEntities.get(Ugos.USER.toString ()).getPermissionsAsString() + "\n" +
			   Ugos.GROUP.toString() + " Permisions: " +
			   		accessEntities.get(Ugos.GROUP.toString()).getPermissionsAsString() + "\n" +
			   Ugos.OTHER.toString() + " Permisions: " + 
			   		accessEntities.get(Ugos.OTHER.toString()).getPermissionsAsString() + "\n";
	}
}


interface Chmodable {
	void setPermissions(Permissions perms);
	Permissions getPermissions();
	String getPermissionsAsString();
}

class AccessEntity implements Chmodable {
	
	private Permissions perms = new Permissions();
	
	AccessEntity(Permissions perms) {
		this.perms = perms;
	}
	public Permissions getPermissions() {
		return this.perms;
	}
	public void setPermissions(Permissions perms) {
		this.perms = perms;
	}
	
	public String getPermissionsAsString() {
		return this.getPermissions().getCurrentPermissionLevelAsString();
	}
}

class User extends AccessEntity {

	User(Permissions perms) {
		super(perms);
	}
}

class Group extends AccessEntity {

	Group(Permissions perms) {
		super(perms);
	}
}

class Other extends AccessEntity {

	Other(Permissions perms) {
		super(perms);
	}
}
